iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0

Oracle

區塊鏈上除了資料公開,防竄改之外,更重要的是如何獲取外界的資訊,並且確定資料是可信任的,而 Oracle「預言機」正是那個能夠讓鏈上取得真實世界資料的關鍵組件;預言機,是建構在圖靈機上用於解答「特定問題集合」的計算機,預言機的出現使的區塊鏈的生態獲得近一步的進化,區塊鏈系統上產生的 DeFi 也大程度仰賴 Oracle 所給予的各項真實世界數據,例如某些加密貨幣、 Token 的匯率等等,藉此讓各式應用能和現實接軌。

智能合約,在以太坊推出後便普遍認為是區塊鏈上必要的組件之一,但眾所周知,區塊鏈並沒有主動獲得資訊的能力,而是被動的接收資訊並且維護這些資訊的正確性,而 Oracle 能夠讓智能合約與外界接軌,那麼就簡單舉個例子說明他是如何運作的 : 當應用程式需要今天某城市的天氣氣象時,將會由智能合約上的 EventLog 寫上 「需要獲得城市的天氣資訊」,而鏈下就會經過發送交易的方式將資訊寫入智能合約之中。

Chainlink

上述提及之 Oracle 概念,其實就和一般開發時使用的 API 如出一轍,既然如此則存在著問題,如 API 故障、數據來源遭駭等等,又由於區塊鏈上應用大多伴隨著金流,且一旦合約部署後便無法更改,因此數據來源的可靠性與穩定性就更顯得重要。

而 Chainlink 是一個為區塊鏈提供預言機(Oracle)服務的平台,能夠為區塊鏈上的智能合約提供現實世界的各項數據,例如上一次總統大選的當選者是誰等等,無法從鏈上取得的資料都能透過 Chainlink 取得並傳輸至鏈上,與一般的 Oracle 不同的是, Chainlink 是一個去中心化的平台,由 Chainlink 取得之資訊會經過整個去中心化網路的判斷進而傳遞事實。

運作模式

Chainlink 採去中心化模式,任何人都可以運行自己的網路,具體來說,欲取得相關數據者會向運行網路者提出購買數據的請求,而 Chainlink 則會隨機選擇節點給出答案,而這些隨機的節點會抵押部分的 Link 代幣作為擔保,接著運用各自的 api 取得數據,提交這些數據後 Chainlink 會再針對這些數據做加權進而產生最終的結果,成功遞交資料的節點會取得額外 Link 代幣作為獎勵,反之,若是遞交的資料為極端值則不會獲得 Link 且將不退回押金。

Link

Link 是一個由 ERC677 協議產生的 Token,而 ERC677 則是一個 ERC20 的擴展,除了 ERC20 的所有函數以外,增加了一個 transferAndCall 的函數

function transferAndCall(address receiver, uint amount, bytes data) returns (bool success)

可以看到 transferAndCall 和一般的 transfer 相比多了 data 參數,而這個 data 參數支援用戶在進行轉帳的同時,也攜帶數據進行轉帳,而若要接收這個 transferAndCall 函數轉帳過來的 Token 則需要用另外撰寫接收函數 onTokenTransfer

function onTokenTransfer(address from, uint256 amount, bytes data) returns (bool success)

Chainlink VRF

經過上述的簡單介紹後相信讀者們對於 Chainlink 已有最基礎的認識,若是想要更詳細的了解,這邊附上 White Paper

接著就進入從上次關卡延伸出來的主題 Chainlink VRF

首先請到測試網領取 Link

接著就進入產生隨機數的實作

請至 訂閱頁面建立訂閱


之後會彈出 Metamask 的確認交易介面,就直接確認囉
再來會需要你輸入資金(Link)

只要兩個就夠囉,加入資產後也會要求你確認一次 Metamask 一樣直接按下 confirm 即可

進到這個頁面後先等一下,
我們打開 remix 貼上以下程式碼並編譯,貼上你的 ID 後部署到測試鏈,再把合約地址貼上

// SPDX-License-Identifier: MIT
// An example of a consumer contract that relies on a subscription for funding.
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

contract VRFv2Consumer is VRFConsumerBaseV2 {
  VRFCoordinatorV2Interface COORDINATOR;

  // Your subscription ID.
  uint64 s_subscriptionId;

  // Goerli coordinator. For other networks,
  // see https://docs.chain.link/docs/vrf-contracts/#configurations
  address vrfCoordinator = 0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D;

  // The gas lane to use, which specifies the maximum gas price to bump to.
  // For a list of available gas lanes on each network,
  // see https://docs.chain.link/docs/vrf-contracts/#configurations
  bytes32 keyHash = 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15;

  // Depends on the number of requested values that you want sent to the
  // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
  // so 100,000 is a safe default for this example contract. Test and adjust
  // this limit based on the network that you select, the size of the request,
  // and the processing of the callback request in the fulfillRandomWords()
  // function.
  uint32 callbackGasLimit = 100000;

  // The default is 3, but you can set this higher.
  uint16 requestConfirmations = 3;

  // For this example, retrieve 2 random values in one request.
  // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
  uint32 numWords =  2;

  uint256[] public s_randomWords;
  uint256 public s_requestId;
  address s_owner;

  constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) {
    COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
    s_owner = msg.sender;
    s_subscriptionId = subscriptionId;
  }

  // Assumes the subscription is funded sufficiently.
  function requestRandomWords() external onlyOwner {
    // Will revert if subscription is not set and funded.
    s_requestId = COORDINATOR.requestRandomWords(
      keyHash,
      s_subscriptionId,
      requestConfirmations,
      callbackGasLimit,
      numWords
    );
  }

  function fulfillRandomWords(
    uint256, /* requestId */
    uint256[] memory randomWords
  ) internal override {
    s_randomWords = randomWords;
  }

  modifier onlyOwner() {
    require(msg.sender == s_owner);
    _;
  }
}

輸入 ID 後部署至測試網

部署完成後回到 Subscription 頁面,點擊 Add consumer 填上你部署的合約地址

一樣請用 Metamask 確認這筆交易

完成後,要呼叫隨機數的合約就會下面
最後回到 Remix 執行 requestRandomWords
執行完畢後就可以在 S_randomWords[0] 裡面看到結果囉。

Reference

https://genesisblockhk.com/zh/crypto-101-what-is-chainlink/
https://chain.link/education/blockchain-oracles
https://www.blocktempo.com/ethfans-chainlink-oracle-eth-smartcontact/
https://www.investors.tw/what-is-chainlink/
https://kknews.cc/zh-tw/code/mrjr2q9.html


上一篇
Day 5 - Coin Flip
下一篇
Day 7 - Telephone
系列文
智能合約漏洞演練 - Ethernaut18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言